agora inbox for pgsql-hackers@postgresql.orghelp / color / mirror / Atom feed
[PATCH v20 1/3] Avoid orphaned objects dependencies 249+ messages / 2 participants [nested] [flat]
* [PATCH v20 1/3] Avoid orphaned objects dependencies @ 2026-04-27 14:01 Bertrand Drouvot <bertranddrouvot.pg@gmail.com> 0 siblings, 0 replies; 249+ messages in thread From: Bertrand Drouvot @ 2026-04-27 14:01 UTC (permalink / raw) Concurrent DDL can create orphaned dependencies in pg_depend, objects referencing other objects that no longer exist. For example: Scenario 1: session 1: begin; drop schema schem; session 2: create a function in the schema schem session 1: commit; With the above, the function created in session 2 would be linked to a non existing schema. Scenario 2: session 1: begin; create a function in the schema schem session 2: drop schema schem; session 1: commit; With the above, the function created in session 1 would be linked to a non existing schema. Fix by acquiring AccessShareLock on referenced objects when recording dependencies. This conflicts with AccessExclusiveLock taken by DROP, preventing the race. After acquiring the lock, verify the object still exists, if it was dropped concurrently, report an error. The lock and check is done in both recordMultipleDependencies() and changeDependencyFor(). The patch adds a few tests for some dependency cases (that would currently produce orphaned objects): - schema and function (as the above scenarios) - alter a dependency (function and schema) - function and arg type - function and return type - function and function - domain and domain - table and type - server and foreign data wrapper Author: Bertrand Drouvot <bertranddrouvot.pg@gmail.com> Reviewed-by: Discussion: https://postgr.es/m/ZiYjn0eVc7pxVY45@ip-10-97-1-34.eu-west-3.compute.internal --- src/backend/catalog/dependency.c | 72 ++++++++++ src/backend/catalog/objectaddress.c | 65 +++++++++ src/backend/catalog/pg_depend.c | 16 ++- src/backend/utils/errcodes.txt | 1 + src/include/catalog/dependency.h | 2 + src/include/catalog/objectaddress.h | 1 + .../expected/test_dependencies_locks.out | 129 ++++++++++++++++++ src/test/isolation/isolation_schedule | 1 + .../specs/test_dependencies_locks.spec | 96 +++++++++++++ src/test/regress/expected/alter_table.out | 11 +- 10 files changed, 386 insertions(+), 8 deletions(-) 26.4% src/backend/catalog/ 41.3% src/test/isolation/expected/ 27.7% src/test/isolation/specs/ 4.3% src/ diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c index fdb8e67e1f5..7e26691393d 100644 --- a/src/backend/catalog/dependency.c +++ b/src/backend/catalog/dependency.c @@ -87,6 +87,7 @@ #include "parser/parsetree.h" #include "rewrite/rewriteRemove.h" #include "storage/lmgr.h" +#include "storage/lock.h" #include "utils/fmgroids.h" #include "utils/lsyscache.h" #include "utils/syscache.h" @@ -1606,6 +1607,77 @@ ReleaseDeletionLock(const ObjectAddress *object) AccessExclusiveLock); } +/* + * LockNotPinnedObject + * + * Lock the object that we are about to record a dependency on. + * After it's locked, verify that it hasn't been dropped while we + * weren't looking. If the object has been dropped, this function + * does not return! + * + * If the caller already holds a lock that conflicts with DROP + * (AccessShareLock or stronger), skip the lock acquisition entirely. + */ +void +LockNotPinnedObject(const ObjectAddress *object) +{ + if (isObjectPinned(object)) + return; + + if (object->classId == RelationRelationId) + { + /* skip shared relations as they are pinned */ + if (IsSharedRelation(object->objectId)) + return; + + /* + * We must be in one of the two following cases that would already + * prevent the relation to be dropped: 1. The relation is already + * locked (could be an existing relation or a relation that we are + * creating). 2. The relation is protected indirectly (i.e an index + * protected by a lock on its table, a table protected by a lock on a + * function that depends of the table...). To avoid any risks, acquire + * a lock if there is none. That may add unnecessary lock for 2. but + * that's worth it. + */ + if (!CheckRelationOidLockedByMe(object->objectId, AccessShareLock, true)) + LockRelationOid(object->objectId, AccessShareLock); + return; + } + else + { + LOCKTAG tag; + + SET_LOCKTAG_OBJECT(tag, + MyDatabaseId, + object->classId, + object->objectId, + 0); + + if (LockHeldByMe(&tag, AccessShareLock, true)) + return; + + /* assume we should lock the whole object not a sub-object */ + LockDatabaseObject(object->classId, object->objectId, 0, AccessShareLock); + } + + /* check if object still exists */ + if (!ObjectByIdExist(object, false)) + { + /* + * It might be possible that we are creating it (for example creating + * a composite type while creating a relation), so bypass the syscache + * lookup and use a SnapshotSelf scan instead to cover this scenario. + */ + if (!ObjectByIdExist(object, true)) + ereport(ERROR, + (errcode(ERRCODE_DEPENDENT_OBJECTS_DOES_NOT_EXIST), + errmsg("dependent object does not exist"), + errdetail("Class OID is %u and object OID is %u", + object->classId, object->objectId))); + } +} + /* * recordDependencyOnExpr - find expression dependencies * diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c index c1862809577..d1ed8188d93 100644 --- a/src/backend/catalog/objectaddress.c +++ b/src/backend/catalog/objectaddress.c @@ -90,6 +90,7 @@ #include "utils/lsyscache.h" #include "utils/memutils.h" #include "utils/regproc.h" +#include "utils/snapmgr.h" #include "utils/syscache.h" /* @@ -2696,6 +2697,70 @@ get_object_namespace(const ObjectAddress *address) return oid; } +/* + * ObjectByIdExist + * + * Return whether the given object exists. + * + * If use_snapshot_self is false, uses the syscache (which sees committed data). + * If use_snapshot_self is true, does a direct catalog scan with SnapshotSelf + * to also see objects created in the current transaction. + */ +bool +ObjectByIdExist(const ObjectAddress *address, bool use_snapshot_self) +{ + HeapTuple tuple; + SysCacheIdentifier cache = SYSCACHEID_INVALID; + + if (!use_snapshot_self) + { + const ObjectPropertyType *property; + + property = get_object_property_data(address->classId); + cache = property->oid_catcache_id; + } + + if (cache != SYSCACHEID_INVALID) + { + tuple = SearchSysCache1(cache, ObjectIdGetDatum(address->objectId)); + + if (!HeapTupleIsValid(tuple)) + return false; + + ReleaseSysCache(tuple); + return true; + } + else + { + Relation rel; + ScanKeyData skey[1]; + SysScanDesc scan; + Snapshot snapshot; + + if (use_snapshot_self) + snapshot = SnapshotSelf; + else + snapshot = NULL; + + rel = table_open(address->classId, AccessShareLock); + + ScanKeyInit(&skey[0], + get_object_attnum_oid(address->classId), + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(address->objectId)); + + scan = systable_beginscan(rel, get_object_oid_index(address->classId), + true, snapshot, 1, skey); + + tuple = systable_getnext(scan); + + systable_endscan(scan); + table_close(rel, AccessShareLock); + + return HeapTupleIsValid(tuple); + } +} + /* * Return ObjectType for the given object type as given by * getObjectTypeDescription; if no valid ObjectType code exists, but it's a diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c index 07c2d41c189..5618e3d26fa 100644 --- a/src/backend/catalog/pg_depend.c +++ b/src/backend/catalog/pg_depend.c @@ -33,8 +33,6 @@ #include "utils/syscache.h" -static bool isObjectPinned(const ObjectAddress *object); - /* * Record a dependency between 2 objects via their respective ObjectAddress. @@ -109,6 +107,12 @@ recordMultipleDependencies(const ObjectAddress *depender, if (isObjectPinned(referenced)) continue; + /* + * Acquire a lock and check object still exists while recording the + * dependency. + */ + LockNotPinnedObject(referenced); + if (slot_init_count < max_slots) { slot[slot_stored_count] = MakeSingleTupleTableSlot(RelationGetDescr(dependDesc), @@ -507,6 +511,12 @@ changeDependencyFor(Oid classId, Oid objectId, return 1; } + /* + * Acquire a lock and check object still exists while changing the + * dependency. + */ + LockNotPinnedObject(&objAddr); + depRel = table_open(DependRelationId, RowExclusiveLock); /* There should be existing dependency record(s), so search. */ @@ -707,7 +717,7 @@ changeDependenciesOn(Oid refClassId, Oid oldRefObjectId, * The passed subId, if any, is ignored; we assume that only whole objects * are pinned (and that this implies pinning their components). */ -static bool +bool isObjectPinned(const ObjectAddress *object) { return IsPinnedObject(object->classId, object->objectId); diff --git a/src/backend/utils/errcodes.txt b/src/backend/utils/errcodes.txt index 5b25402ebbe..58b498f68fc 100644 --- a/src/backend/utils/errcodes.txt +++ b/src/backend/utils/errcodes.txt @@ -278,6 +278,7 @@ Section: Class 2B - Dependent Privilege Descriptors Still Exist 2B000 E ERRCODE_DEPENDENT_PRIVILEGE_DESCRIPTORS_STILL_EXIST dependent_privilege_descriptors_still_exist 2BP01 E ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST dependent_objects_still_exist +2BP02 E ERRCODE_DEPENDENT_OBJECTS_DOES_NOT_EXIST dependent_objects_does_not_exist Section: Class 2D - Invalid Transaction Termination diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h index 2f3c1eae3c7..fa508ea70c6 100644 --- a/src/include/catalog/dependency.h +++ b/src/include/catalog/dependency.h @@ -101,6 +101,8 @@ typedef struct ObjectAddresses ObjectAddresses; /* in dependency.c */ extern void AcquireDeletionLock(const ObjectAddress *object, int flags); +extern void LockNotPinnedObject(const ObjectAddress *object); +extern bool isObjectPinned(const ObjectAddress *object); extern void ReleaseDeletionLock(const ObjectAddress *object); diff --git a/src/include/catalog/objectaddress.h b/src/include/catalog/objectaddress.h index 1f965e1faef..960b7e4bfa6 100644 --- a/src/include/catalog/objectaddress.h +++ b/src/include/catalog/objectaddress.h @@ -54,6 +54,7 @@ extern void check_object_ownership(Oid roleid, Node *object, Relation relation); extern Oid get_object_namespace(const ObjectAddress *address); +extern bool ObjectByIdExist(const ObjectAddress *address, bool use_snapshot_self); extern bool is_objectclass_supported(Oid class_id); extern const char *get_object_class_descr(Oid class_id); diff --git a/src/test/isolation/expected/test_dependencies_locks.out b/src/test/isolation/expected/test_dependencies_locks.out new file mode 100644 index 00000000000..820680f5e16 --- /dev/null +++ b/src/test/isolation/expected/test_dependencies_locks.out @@ -0,0 +1,129 @@ +Parsed test spec with 2 sessions + +starting permutation: s1_begin s1_create_function_in_schema s2_drop_schema s1_commit +step s1_begin: BEGIN; +step s1_create_function_in_schema: CREATE FUNCTION testschema.foo() RETURNS int AS 'select 1' LANGUAGE sql; +step s2_drop_schema: DROP SCHEMA testschema; <waiting ...> +step s1_commit: COMMIT; +step s2_drop_schema: <... completed> +ERROR: cannot drop schema testschema because other objects depend on it + +starting permutation: s2_begin s2_drop_schema s1_create_function_in_schema s2_commit +step s2_begin: BEGIN; +step s2_drop_schema: DROP SCHEMA testschema; +step s1_create_function_in_schema: CREATE FUNCTION testschema.foo() RETURNS int AS 'select 1' LANGUAGE sql; <waiting ...> +step s2_commit: COMMIT; +step s1_create_function_in_schema: <... completed> +ERROR: dependent object does not exist + +starting permutation: s1_begin s1_alter_function_schema s2_drop_alterschema s1_commit +step s1_begin: BEGIN; +step s1_alter_function_schema: ALTER FUNCTION public.falter() SET SCHEMA alterschema; +step s2_drop_alterschema: DROP SCHEMA alterschema; <waiting ...> +step s1_commit: COMMIT; +step s2_drop_alterschema: <... completed> +ERROR: cannot drop schema alterschema because other objects depend on it + +starting permutation: s2_begin s2_drop_alterschema s1_alter_function_schema s2_commit +step s2_begin: BEGIN; +step s2_drop_alterschema: DROP SCHEMA alterschema; +step s1_alter_function_schema: ALTER FUNCTION public.falter() SET SCHEMA alterschema; <waiting ...> +step s2_commit: COMMIT; +step s1_alter_function_schema: <... completed> +ERROR: dependent object does not exist + +starting permutation: s1_begin s1_create_function_with_argtype s2_drop_foo_type s1_commit +step s1_begin: BEGIN; +step s1_create_function_with_argtype: CREATE FUNCTION fooargtype(num foo) RETURNS int AS 'select 1' LANGUAGE sql; +step s2_drop_foo_type: DROP TYPE public.foo; <waiting ...> +step s1_commit: COMMIT; +step s2_drop_foo_type: <... completed> +ERROR: cannot drop type foo because other objects depend on it + +starting permutation: s2_begin s2_drop_foo_type s1_create_function_with_argtype s2_commit +step s2_begin: BEGIN; +step s2_drop_foo_type: DROP TYPE public.foo; +step s1_create_function_with_argtype: CREATE FUNCTION fooargtype(num foo) RETURNS int AS 'select 1' LANGUAGE sql; <waiting ...> +step s2_commit: COMMIT; +step s1_create_function_with_argtype: <... completed> +ERROR: dependent object does not exist + +starting permutation: s1_begin s1_create_function_with_rettype s2_drop_foo_rettype s1_commit +step s1_begin: BEGIN; +step s1_create_function_with_rettype: CREATE FUNCTION footrettype() RETURNS id LANGUAGE sql RETURN 1; +step s2_drop_foo_rettype: DROP DOMAIN id; <waiting ...> +step s1_commit: COMMIT; +step s2_drop_foo_rettype: <... completed> +ERROR: cannot drop type id because other objects depend on it + +starting permutation: s2_begin s2_drop_foo_rettype s1_create_function_with_rettype s2_commit +step s2_begin: BEGIN; +step s2_drop_foo_rettype: DROP DOMAIN id; +step s1_create_function_with_rettype: CREATE FUNCTION footrettype() RETURNS id LANGUAGE sql RETURN 1; <waiting ...> +step s2_commit: COMMIT; +step s1_create_function_with_rettype: <... completed> +ERROR: dependent object does not exist + +starting permutation: s1_begin s1_create_function_with_function s2_drop_function_f s1_commit +step s1_begin: BEGIN; +step s1_create_function_with_function: CREATE FUNCTION foofunc() RETURNS int LANGUAGE SQL RETURN f() + 1; +step s2_drop_function_f: DROP FUNCTION f(); <waiting ...> +step s1_commit: COMMIT; +step s2_drop_function_f: <... completed> +ERROR: cannot drop function f() because other objects depend on it + +starting permutation: s2_begin s2_drop_function_f s1_create_function_with_function s2_commit +step s2_begin: BEGIN; +step s2_drop_function_f: DROP FUNCTION f(); +step s1_create_function_with_function: CREATE FUNCTION foofunc() RETURNS int LANGUAGE SQL RETURN f() + 1; <waiting ...> +step s2_commit: COMMIT; +step s1_create_function_with_function: <... completed> +ERROR: dependent object does not exist + +starting permutation: s1_begin s1_create_domain_with_domain s2_drop_domain_id s1_commit +step s1_begin: BEGIN; +step s1_create_domain_with_domain: CREATE DOMAIN idid as id; +step s2_drop_domain_id: DROP DOMAIN id; <waiting ...> +step s1_commit: COMMIT; +step s2_drop_domain_id: <... completed> +ERROR: cannot drop type id because other objects depend on it + +starting permutation: s2_begin s2_drop_domain_id s1_create_domain_with_domain s2_commit +step s2_begin: BEGIN; +step s2_drop_domain_id: DROP DOMAIN id; +step s1_create_domain_with_domain: CREATE DOMAIN idid as id; <waiting ...> +step s2_commit: COMMIT; +step s1_create_domain_with_domain: <... completed> +ERROR: dependent object does not exist + +starting permutation: s1_begin s1_create_table_with_type s2_drop_footab_type s1_commit +step s1_begin: BEGIN; +step s1_create_table_with_type: CREATE TABLE tabtype(a footab); +step s2_drop_footab_type: DROP TYPE public.footab; <waiting ...> +step s1_commit: COMMIT; +step s2_drop_footab_type: <... completed> +ERROR: cannot drop type footab because other objects depend on it + +starting permutation: s2_begin s2_drop_footab_type s1_create_table_with_type s2_commit +step s2_begin: BEGIN; +step s2_drop_footab_type: DROP TYPE public.footab; +step s1_create_table_with_type: CREATE TABLE tabtype(a footab); <waiting ...> +step s2_commit: COMMIT; +step s1_create_table_with_type: <... completed> +ERROR: dependent object does not exist + +starting permutation: s1_begin s1_create_server_with_fdw_wrapper s2_drop_fdw_wrapper s1_commit +step s1_begin: BEGIN; +step s1_create_server_with_fdw_wrapper: CREATE SERVER srv_fdw_wrapper FOREIGN DATA WRAPPER fdw_wrapper; +step s2_drop_fdw_wrapper: DROP FOREIGN DATA WRAPPER fdw_wrapper RESTRICT; <waiting ...> +step s1_commit: COMMIT; +step s2_drop_fdw_wrapper: <... completed> +ERROR: cannot drop foreign-data wrapper fdw_wrapper because other objects depend on it + +starting permutation: s2_begin s2_drop_fdw_wrapper s1_create_server_with_fdw_wrapper s2_commit +step s2_begin: BEGIN; +step s2_drop_fdw_wrapper: DROP FOREIGN DATA WRAPPER fdw_wrapper RESTRICT; +step s1_create_server_with_fdw_wrapper: CREATE SERVER srv_fdw_wrapper FOREIGN DATA WRAPPER fdw_wrapper; <waiting ...> +step s2_commit: COMMIT; +step s1_create_server_with_fdw_wrapper: <... completed> +ERROR: dependent object does not exist diff --git a/src/test/isolation/isolation_schedule b/src/test/isolation/isolation_schedule index 1578ba191c8..83f626d51b5 100644 --- a/src/test/isolation/isolation_schedule +++ b/src/test/isolation/isolation_schedule @@ -126,3 +126,4 @@ test: serializable-parallel-3 test: matview-write-skew test: lock-nowait test: for-portion-of +test: test_dependencies_locks \ No newline at end of file diff --git a/src/test/isolation/specs/test_dependencies_locks.spec b/src/test/isolation/specs/test_dependencies_locks.spec new file mode 100644 index 00000000000..ee4130b2dc4 --- /dev/null +++ b/src/test/isolation/specs/test_dependencies_locks.spec @@ -0,0 +1,96 @@ +# Test that concurrent DDL properly prevents orphaned dependencies. +# +# When session 1 creates an object that depends on a referenced object, +# and session 2 concurrently drops that referenced object, the lock +# acquired during dependency recording must prevent the drop or the +# create must fail with "dependent object does not exist". + +setup +{ + CREATE SCHEMA testschema; + CREATE SCHEMA alterschema; + CREATE TYPE public.foo as enum ('one', 'two'); + CREATE TYPE public.footab as enum ('three', 'four'); + CREATE DOMAIN id AS int; + CREATE FUNCTION f() RETURNS int LANGUAGE SQL RETURN 1; + CREATE FUNCTION public.falter() RETURNS int LANGUAGE SQL RETURN 1; + CREATE FOREIGN DATA WRAPPER fdw_wrapper; +} + +teardown +{ + DROP FUNCTION IF EXISTS testschema.foo(); + DROP FUNCTION IF EXISTS fooargtype(num foo); + DROP FUNCTION IF EXISTS footrettype(); + DROP FUNCTION IF EXISTS foofunc(); + DROP FUNCTION IF EXISTS public.falter(); + DROP FUNCTION IF EXISTS alterschema.falter(); + DROP DOMAIN IF EXISTS idid; + DROP SERVER IF EXISTS srv_fdw_wrapper; + DROP TABLE IF EXISTS tabtype; + DROP SCHEMA IF EXISTS testschema; + DROP SCHEMA IF EXISTS alterschema; + DROP TYPE IF EXISTS public.foo; + DROP TYPE IF EXISTS public.footab; + DROP DOMAIN IF EXISTS id; + DROP FUNCTION IF EXISTS f(); + DROP FOREIGN DATA WRAPPER IF EXISTS fdw_wrapper; +} + +session "s1" + +step "s1_begin" { BEGIN; } +step "s1_create_function_in_schema" { CREATE FUNCTION testschema.foo() RETURNS int AS 'select 1' LANGUAGE sql; } +step "s1_create_function_with_argtype" { CREATE FUNCTION fooargtype(num foo) RETURNS int AS 'select 1' LANGUAGE sql; } +step "s1_create_function_with_rettype" { CREATE FUNCTION footrettype() RETURNS id LANGUAGE sql RETURN 1; } +step "s1_create_function_with_function" { CREATE FUNCTION foofunc() RETURNS int LANGUAGE SQL RETURN f() + 1; } +step "s1_alter_function_schema" { ALTER FUNCTION public.falter() SET SCHEMA alterschema; } +step "s1_create_domain_with_domain" { CREATE DOMAIN idid as id; } +step "s1_create_table_with_type" { CREATE TABLE tabtype(a footab); } +step "s1_create_server_with_fdw_wrapper" { CREATE SERVER srv_fdw_wrapper FOREIGN DATA WRAPPER fdw_wrapper; } +step "s1_commit" { COMMIT; } + +session "s2" + +step "s2_begin" { BEGIN; } +step "s2_drop_schema" { DROP SCHEMA testschema; } +step "s2_drop_alterschema" { DROP SCHEMA alterschema; } +step "s2_drop_foo_type" { DROP TYPE public.foo; } +step "s2_drop_foo_rettype" { DROP DOMAIN id; } +step "s2_drop_footab_type" { DROP TYPE public.footab; } +step "s2_drop_function_f" { DROP FUNCTION f(); } +step "s2_drop_domain_id" { DROP DOMAIN id; } +step "s2_drop_fdw_wrapper" { DROP FOREIGN DATA WRAPPER fdw_wrapper RESTRICT; } +step "s2_commit" { COMMIT; } + +# function - schema +permutation "s1_begin" "s1_create_function_in_schema" "s2_drop_schema" "s1_commit" +permutation "s2_begin" "s2_drop_schema" "s1_create_function_in_schema" "s2_commit" + +# alter function - schema +permutation "s1_begin" "s1_alter_function_schema" "s2_drop_alterschema" "s1_commit" +permutation "s2_begin" "s2_drop_alterschema" "s1_alter_function_schema" "s2_commit" + +# function - argtype +permutation "s1_begin" "s1_create_function_with_argtype" "s2_drop_foo_type" "s1_commit" +permutation "s2_begin" "s2_drop_foo_type" "s1_create_function_with_argtype" "s2_commit" + +# function - rettype +permutation "s1_begin" "s1_create_function_with_rettype" "s2_drop_foo_rettype" "s1_commit" +permutation "s2_begin" "s2_drop_foo_rettype" "s1_create_function_with_rettype" "s2_commit" + +# function - function +permutation "s1_begin" "s1_create_function_with_function" "s2_drop_function_f" "s1_commit" +permutation "s2_begin" "s2_drop_function_f" "s1_create_function_with_function" "s2_commit" + +# domain - domain +permutation "s1_begin" "s1_create_domain_with_domain" "s2_drop_domain_id" "s1_commit" +permutation "s2_begin" "s2_drop_domain_id" "s1_create_domain_with_domain" "s2_commit" + +# table - type +permutation "s1_begin" "s1_create_table_with_type" "s2_drop_footab_type" "s1_commit" +permutation "s2_begin" "s2_drop_footab_type" "s1_create_table_with_type" "s2_commit" + +# server - foreign data wrapper +permutation "s1_begin" "s1_create_server_with_fdw_wrapper" "s2_drop_fdw_wrapper" "s1_commit" +permutation "s2_begin" "s2_drop_fdw_wrapper" "s1_create_server_with_fdw_wrapper" "s2_commit" diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out index 6dd22be0e8d..b891d68d4a7 100644 --- a/src/test/regress/expected/alter_table.out +++ b/src/test/regress/expected/alter_table.out @@ -2949,11 +2949,12 @@ begin; alter table alterlock2 add constraint alterlock2nv foreign key (f1) references alterlock (f1) NOT VALID; select * from my_locks order by 1; - relname | max_lockmode -------------+----------------------- - alterlock | ShareRowExclusiveLock - alterlock2 | ShareRowExclusiveLock -(2 rows) + relname | max_lockmode +----------------+----------------------- + alterlock | ShareRowExclusiveLock + alterlock2 | ShareRowExclusiveLock + alterlock_pkey | AccessShareLock +(3 rows) commit; begin; -- 2.34.1 --zB/Wek73NRZcta1g Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v20-0002-Lock-referenced-objects-before-permission-checks.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
* [PATCH v6a 2/5] gha: Andres' revisions @ 2026-06-01 19:09 Andres Freund <andres@anarazel.de> 0 siblings, 0 replies; 249+ messages in thread From: Andres Freund @ 2026-06-01 19:09 UTC (permalink / raw) --- .github/workflows/postgresql-ci.yml | 834 +++++++++++++++------------- 1 file changed, 447 insertions(+), 387 deletions(-) diff --git a/.github/workflows/postgresql-ci.yml b/.github/workflows/postgresql-ci.yml index a7ef0bee94d..e2795ca0ffb 100644 --- a/.github/workflows/postgresql-ci.yml +++ b/.github/workflows/postgresql-ci.yml @@ -4,6 +4,7 @@ name: GitHub Actions CI on: push: + # FIXME: Should we also run on PRs? # Restrict GITHUB_TOKEN to the minimum the jobs need: reading repo # contents during checkout. @@ -13,6 +14,7 @@ permissions: concurrency: group: ${{ github.workflow }}-${{ github.ref }} # Never cancel in-progress runs on master to ensure all commits are tested. + # FIXME: Should also not cancel REL_XY_STABLE cancel-in-progress: ${{ github.ref != 'refs/heads/master' }} env: @@ -20,9 +22,19 @@ env: # concurrent jobs and retrying older runs have a chance of working. CLONE_DEPTH: 500 + # At the moment all jobs use 4vcore runners, and none seems to benefit from + # increasing concurrency further. + BUILD_JOBS: 4 + + # It's possible that some jobs benefit from an increased test concurrency, + # but a default of 4 is a safe bet. Individual jobs can override. + TEST_JOBS: 4 + CCACHE_MAXSIZE: "250M" + CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # check target for the autoconf builds + # Check target for the autoconf builds. Can be set to e.g. check to only + # only test the main regression tests. CHECK: check-world PROVE_FLAGS=--timer CHECKFLAGS: -Otarget @@ -30,6 +42,11 @@ env: # errors/warnings in one place. MBUILD_TARGET: all testprep MTEST_ARGS: --print-errorlogs --no-rebuild -C build + + # Can be set to a non-empty value to run a limited set of tests + # (e.g. --suite regress to only run the main regression tests). + MTEST_TARGET: + PGCTLTIMEOUT: 120 # avoids spurious failures during parallel tests TEMP_CONFIG: ${{ github.workspace }}/src/tools/ci/pg_ci_base.conf PG_TEST_EXTRA: kerberos ldap ssl libpq_encryption load_balance oauth @@ -79,20 +96,16 @@ env: --with-uuid=ossp --with-zstd - # Debian Trixie container image used by all Linux jobs. Built by + # Debian Trixie containers used by all Linux jobs. Built by # 'https://github.com/anarazel/pg-vm-images/';. - LINUX_CI_IMAGE: us-docker.pkg.dev/pg-ci-images/ci/linux_debian_trixie_ci:latest + CONTAINER_REPO: ghcr.io/anarazel/pg-vm-images/gha_main + CONTAINER_LINUX_CI: linux_debian_trixie_ci:latest + CONTAINER_LINUX_CI_DOCS: linux_debian_trixie_ci_docs:latest # The full set of OS / job selectors recognized by the `ci-os-only:` # commit-message directive parsed in the `setup` job below. CI_OS_ONLY_JOBS: "linux macos windows mingw compilerwarnings sanitycheck" - _LOG_PATHS: &log_paths | - build*/testrun/**/*.log - build*/testrun/**/*.diffs - build*/testrun/**/regress_log_* - build*/meson-logs/*.txt - jobs: # Parse "ci-os-only: ..." from the commit message and expose flags @@ -111,14 +124,26 @@ jobs: # Re-export workflow-level env vars that other jobs need to reference # from contexts (e.g. `jobs.<id>.container.image`) where the `env` # context is not available. - linux_ci_image: ${{ env.LINUX_CI_IMAGE }} + container_linux_ci: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI }} + container_linux_ci_docs: ${{ env.CONTAINER_REPO }}/${{ env.CONTAINER_LINUX_CI_DOCS }} steps: + # Anchor reused by other jobs further down. GitHub Actions supports YAML + # anchors/aliases but not merge keys, so the alias copies the whole step + # verbatim. The anchor is resolved at YAML parse time, so the alias + # keeps working even if this job were to be skipped at runtime. + - &nix_sysinfo_step + name: sysinfo + run: | + id + uname -a + ulimit -a -H && ulimit -a -S + env + - id: os env: MSG: ${{ github.event.head_commit.message }} shell: bash run: | - set -e all_os=${CI_OS_ONLY_JOBS} if printf '%s\n' "$MSG" | grep -qE '^ci-os-only: '; then sel=$(printf '%s\n' "$MSG" | sed -n 's/^ci-os-only: //p' | head -n 1) @@ -145,199 +170,22 @@ jobs: sanity-check: name: SanityCheck needs: setup - if: needs.setup.outputs.sanitycheck == 'true' + if: | + !cancelled() && + needs.setup.outputs.sanitycheck == 'true' runs-on: ubuntu-latest timeout-minutes: 15 - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + container: &linux_ci_container + image: ${{ needs.setup.outputs.container_linux_ci }} + + # Options passed to all linux containers. Not all of the jobs need + # all of them, but it's easier to just define them centrally. + # # --privileged is needed so the prepare step can write to sysctls # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern. - options: --privileged - env: - BUILD_JOBS: 8 - TEST_JOBS: 8 - CCACHE_DIR: ${{ github.workspace }}/ccache_dir - # no options enabled, should be small - CCACHE_MAXSIZE: "150M" - steps: - # Anchor reused by other jobs further down. GitHub Actions supports - # YAML anchors/aliases but not merge keys, so the alias copies the - # whole step verbatim. The anchor is resolved at YAML parse time, so the - # alias keeps working even if this job is skipped at runtime. - - &checkout_step - uses: actions/checkout@v6 - with: - fetch-depth: ${{ env.CLONE_DEPTH }} - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-sanitycheck-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-sanitycheck-${{ github.ref_name }}- - ccache-sanitycheck- - - - name: Prepare workspace - run: | - whoami - useradd -m postgres - chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" - - - name: Configure - run: | - su postgres <<-'EOF' - set -e - meson setup \ - --buildtype=debug \ - --auto-features=disabled \ - -Ddefault_library=shared \ - -Dtap_tests=enabled \ - build - EOF - - - name: Build - run: | - su postgres <<EOF - set -e - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - EOF - - # Run a minimal set of tests. The main regression tests take too long - # for this purpose. For now this is a random quick pg_regress style - # test, and a tap test that exercises both a frontend binary and the - # backend. - - name: Test - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - meson test ${MTEST_ARGS} --suite setup - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} \ - cube/regress pg_ctl/001_start_stop - EOF - - - name: Core backtraces - if: failure() - run: | - mkdir -m 770 /tmp/cores - find / -maxdepth 1 -type f -name 'core*' -exec mv '{}' /tmp/cores/ \; - src/tools/ci/cores_backtrace.sh linux /tmp/cores - - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: sanitycheck-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore - - - # Build & test postgres on Linux in three configurations. - # - # Autoconf: - # - Uses address sanitizer (sanitizer failures are typically printed in - # the server log) - # - Configures postgres with a small segment size - # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range - # - # Meson: - # - Test both 64- and 32-bit builds - # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures - # are typically printed in the server log) - # - Uses io_method=io_uring - # - Uses meson feature autodetection - # - 32-bit build tests with LANG=C to give ICU some buildfarm-uncovered - # coverage. Also, newer Python insists on changing LC_CTYPE away from C, - # prevent that with PYTHONCOERCECLOCALE. - # - # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes - # print_stacktraces=1,verbosity=2, duh - # detect_leaks=0: too many uninteresting leak errors in short-lived binaries - linux: - name: Linux - ${{ matrix.name }} - needs: [setup, sanity-check] - if: | - !cancelled() && - needs.setup.outputs.linux == 'true' && - needs.sanity-check.result != 'failure' - runs-on: ubuntu-latest - timeout-minutes: 60 - strategy: - fail-fast: false - matrix: - include: - - name: Autoconf - slug: autoconf - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=address - pg_test_pg_combinebackup_mode: '--copy-file-range' - configure: | - ./configure \ - --enable-cassert --enable-injection-points --enable-debug \ - --enable-tap-tests --enable-nls \ - --with-segsize-blocks=6 \ - --with-libnuma \ - --with-liburing \ - ${LINUX_CONFIGURE_FEATURES} \ - CLANG="ccache clang" - build: | - make -s -j${BUILD_JOBS} world-bin - test: | - make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} - logs_paths: | - **/*.log - **/*.diffs - **/regress_log_* - - - name: Meson (64-bit) - slug: meson-64 - cc: ccache gcc - cxx: ccache g++ - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - -Dllvm=enabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - - - name: Meson (32-bit) - slug: meson-32 - cc: ccache gcc -m32 - cxx: ccache g++ -m32 - sanitizer_flags: -fsanitize=alignment,undefined - pg_test_initdb_extra_opts: '-c io_method=io_uring' - configure: | - meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ - -Duuid=e2fs \ - --buildtype=debug \ - --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ - -DPERL=perl5.40-i386-linux-gnu \ - -Dlibnuma=disabled \ - build - build: | - ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} - ninja -C build -t missingdeps - test: | - PYTHONCOERCECLOCALE=0 LANG=C \ - meson test ${MTEST_ARGS} -C build --num-processes ${TEST_JOBS} - logs_paths: *log_paths - container: - image: ${{ needs.setup.outputs.linux_ci_image }} + # set kernel.core_pattern and (for the meson entries) to flip + # kernel.io_uring_disabled (default 2 on recent GH runner kernels). + # # Share the host PID + IPC namespaces. 017_shm.pl rapidly creates, # kill9's, and restarts postgres; with the container's small PID # space a new postgres can recycle the dead postmaster's PID before @@ -347,46 +195,36 @@ jobs: # # --ulimit raises memlock and core dump size. Memlock is needed for # running the AIO tests. - # - # --privileged is needed so the prepare step can write to sysctls - # under /proc/sys (it's mounted read-only without it). We use it to - # set kernel.core_pattern and (for the meson entries) to flip - # kernel.io_uring_disabled (default 2 on recent GH runner kernels). - options: --pid=host --ipc=host --ulimit memlock=-1:-1 --privileged + options: &linux_container_options | + --privileged --pid=host --ipc=host --ulimit memlock=-1:-1 env: - BUILD_JOBS: 4 - TEST_JOBS: 8 - CCACHE_DIR: /tmp/ccache_dir - DEBUGINFOD_URLS: "https://debuginfod.debian.net"; - - UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 - ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0:detect_stack_use_after_return=0 - CFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - CXXFLAGS: -Og -ggdb -fno-sanitize-recover=all ${{ matrix.sanitizer_flags }} - LDFLAGS: ${{ matrix.sanitizer_flags }} - CC: ${{ matrix.cc }} - CXX: ${{ matrix.cxx }} - - PG_TEST_INITDB_EXTRA_OPTS: ${{ matrix.pg_test_initdb_extra_opts }} - PG_TEST_PG_COMBINEBACKUP_MODE: ${{ matrix.pg_test_pg_combinebackup_mode }} + # no options enabled, should be small + CCACHE_MAXSIZE: "150M" steps: - - *checkout_step + - *nix_sysinfo_step - - name: Restore ccache - uses: actions/cache@v5 + - &checkout_step + uses: actions/checkout@v6 + with: + fetch-depth: ${{ env.CLONE_DEPTH }} + + - &ccache_restore_step + name: Restore ccache + id: ccache_restore + uses: actions/cache/restore@v5 with: path: ${{ env.CCACHE_DIR }} - key: ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}-${{ github.run_id }} + key: &ccache_key | + ccache-${{ github.job }}-${{ github.ref_name }}-${{ github.run_id }}-${{ github.run_attempt }} restore-keys: | - ccache-linux-${{ matrix.slug }}-${{ github.ref_name }}- - ccache-linux-${{ matrix.slug }}- + ccache-${{ github.job }}-${{ github.ref_name }}- + ccache-${{ github.job }}- - - name: Prepare workspace + - &linux_prepare_workspace + name: Prepare workspace run: | useradd -m postgres chown -R postgres:postgres . - mkdir -p "$CCACHE_DIR" - chown -R postgres:postgres "$CCACHE_DIR" mkdir -m 770 /tmp/cores chown root:postgres /tmp/cores sysctl kernel.core_pattern='/tmp/cores/%e-%s-%p.core' @@ -400,41 +238,283 @@ jobs: 127.0.0.3 pg-loadbalancetest EOF + # By using a shell that includes su, the run commands themselves get + # simpler. As there are quite a few commands that need to use su... - name: Configure + shell: &su_postgres_shell | + su postgres -c "bash --noprofile --norc -eo pipefail {0}" run: | - su postgres <<EOF - set -e - ${{ matrix.configure }} - EOF + meson setup \ + --buildtype=debug \ + --auto-features=disabled \ + -Ddefault_library=shared \ + -Dtap_tests=enabled \ + build - name: Build - run: | - su postgres <<EOF - set -e - ${{ matrix.build }} - EOF + shell: *su_postgres_shell + run: &ninja_build_command | + ninja -C build -j${{env.BUILD_JOBS}} ${{env.MBUILD_TARGET}} + ninja -C build -t missingdeps - - name: Test world - run: | - su postgres <<EOF - set -e - ulimit -c unlimited - ${{ matrix.test }} - EOF + # FIXME: As long as we use per-run ccache caches, we should probably add + # a step that checks if there is sufficient new content to warrant + # saving the new cache. + - &ccache_save_step + name: Save ccache + uses: actions/cache/save@v5 + with: + path: ${{ env.CCACHE_DIR }} + key: ${{ steps.ccache_restore.outputs.cache-primary-key }} - - name: Core backtraces - if: failure() + # Run a minimal set of tests. The main regression tests take too long + # for this purpose. For now this is a random quick pg_regress style + # test, and a tap test that exercises both a frontend binary and the + # backend. + # + # To allow the command below to be reused by later tasks, we allow + # adding "setup" commands to be specified via the ADDITIONAL_SETUP + # environment variable. + # + # Note that this command is used on all platforms, therefore one needs + # to be careful about using only ${{env.}} variable references, + # linebreaks etc. + - name: Test + shell: *su_postgres_shell + env: + MTEST_TARGET: cube/regress pg_ctl/001_start_stop + run: &meson_test_world_cmd | + ${{case(runner.os == 'Windows', '', 'ulimit -c unlimited')}} + + ${{env.ADDITIONAL_SETUP}} + + echo ::group::test_setup + meson test ${{env.MTEST_ARGS}} --suite setup --logbase setup + echo ::endgroup:: + + meson test ${{env.MTEST_ARGS}} --num-processes ${{env.TEST_JOBS}} ${{env.MTEST_TARGET}} + + - &linux_collect_cores + name: Core backtraces + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh linux /tmp/cores - - name: Upload logs - if: failure() + # Note that this is used for both meson and autoconf builds + - &upload_logs_step + name: Upload logs + if: failure() && !cancelled() uses: actions/upload-artifact@v7 with: - name: linux-${{ matrix.slug }}-logs-${{ github.run_id }} - path: ${{ matrix.logs_paths }} + name: logs-${{ github.job }}-${{ github.run_id }}-${{ github.run_attempt }} + path: | + **/*.log + **/*.diffs + **/regress_log_* + **/crashlog-*.txt if-no-files-found: ignore + # Linux, Autoconf + # + # SPECIAL: + # - Uses address sanitizer (sanitizer failures are typically printed in + # the server log) + # - Configures postgres with a small segment size + # - Uses PG_TEST_PG_COMBINEBACKUP_MODE=--copy-file-range + linux-autoconf: + name: Linux - Autoconf + needs: [setup, sanity-check] + if: &linux_job_if | + !cancelled() && + needs.setup.outputs.linux == 'true' && + needs.sanity-check.result != 'failure' + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + + env: &linux_env + # Add both debian and linux, as symbols from the host can be visible during profiling + DEBUGINFOD_URLS: "https://debuginfod.debian.net https://debuginfod.ubuntu.com"; + # Use -O2 to reduce the test times, use -fno-sanitize-recover=all to make sanitizer test + # failures visible. + CFLAGS: -O2 -ggdb -fno-sanitize-recover=all + CXXFLAGS: -O2 -ggdb -fno-sanitize-recover=all + LDFLAGS: + CC: ccache gcc + CXX: ccache g++ + CLANG: ccache clang + + # Configure sanitizer runtime behavior to be suitable for running tests: + # disable_coredump=0, abort_on_error=1: for useful backtraces in case of crashes + # print_stacktraces=1,verbosity=2, duh + # detect_leaks=0: too many uninteresting leak errors in short-lived binaries + UBSAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:verbosity=2 + ASAN_OPTIONS: print_stacktrace=1:disable_coredump=0:abort_on_error=1:detect_leaks=0 + + steps: + # GitHub Actions does not make it easy to share some, but not all, + # environment variables between related tasks. We solve that for the + # linux- tasks by updating the environment variables programmatically. + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=address + PG_TEST_PG_COMBINEBACKUP_MODE: --copy-file-range + run: &linux_update_config_cmd | + echo "CFLAGS=$CFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "CXXFLAGS=$CXXFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + echo "LDFLAGS=$LDFLAGS ${SANITIZER_FLAGS}" >> "$GITHUB_ENV" + + echo "CC=${CC}" >> "$GITHUB_ENV" + echo "CXX=${CXX}" >> "$GITHUB_ENV" + + echo "PG_TEST_INITDB_EXTRA_OPTS=${PG_TEST_INITDB_EXTRA_OPTS}" >> "$GITHUB_ENV" + echo "PG_TEST_PG_COMBINEBACKUP_MODE=${PG_TEST_PG_COMBINEBACKUP_MODE}" >> "$GITHUB_ENV" + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + ./configure \ + --enable-cassert --enable-injection-points --enable-debug \ + --enable-tap-tests --enable-nls \ + --with-segsize-blocks=6 \ + --with-libnuma \ + --with-liburing \ + ${LINUX_CONFIGURE_FEATURES} + + - name: Build + shell: *su_postgres_shell + run: | + make -s -j${BUILD_JOBS} world-bin + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: | + make -s ${CHECK} ${CHECKFLAGS} -j${TEST_JOBS} + + - *linux_collect_cores + - *upload_logs_step + + + # Linux Meson, 32 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + # - tests with LANG=C to give ICU some buildfarm-uncovered coverage. Also, + # newer Python insists on changing LC_CTYPE away from C, prevent that with + # PYTHONCOERCECLOCALE. + linux-meson-32: + name: Linux - Meson (32-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + CC: ccache gcc -m32 + CXX: ccache g++ -m32 + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + --pkg-config-path /usr/lib/i386-linux-gnu/pkgconfig/ \ + -DPERL=perl5.40-i386-linux-gnu \ + -Dlibnuma=disabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + env: + PYTHONCOERCECLOCALE: 0 + LANG: C + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # Linux Meson, 64 bit + # + # SPECIAL: + # - Uses undefined behaviour and alignment sanitizers, (sanitizer failures + # are typically printed in the server log) + # - Uses io_method=io_uring + # - Uses meson feature autodetection + linux-meson-64: + name: Linux - Meson (64-bit) + needs: [setup, sanity-check] + if: *linux_job_if + runs-on: ubuntu-latest + container: *linux_ci_container + timeout-minutes: 60 + env: *linux_env + + steps: + - name: Update Environment + env: + SANITIZER_FLAGS: -fsanitize=alignment,undefined + PG_TEST_INITDB_EXTRA_OPTS: -c io_method=io_uring + run: *linux_update_config_cmd + + - *nix_sysinfo_step + - *checkout_step + - *ccache_restore_step + - *linux_prepare_workspace + + - name: Configure + shell: *su_postgres_shell + run: | + meson setup \ + ${MESON_COMMON_PG_CONFIG_ARGS} \ + -Duuid=e2fs \ + --buildtype=debug \ + -Dllvm=enabled \ + build + + - name: Build + shell: *su_postgres_shell + run: *ninja_build_command + + - *ccache_save_step + + - name: Test world + shell: *su_postgres_shell + run: *meson_test_world_cmd + + - *linux_collect_cores + - *upload_logs_step + + # SPECIAL: # - Enables --clone for pg_upgrade and pg_combinebackup # - Specifies configuration options that test reading/writing/copying of node trees @@ -449,13 +529,6 @@ jobs: runs-on: macos-15 timeout-minutes: 60 env: - BUILD_JOBS: 4 - # Test performance regresses noticeably when using all cores. 8 works OK. - # https://postgr.es/m/20220927040208.l3shfcidovpzqxfh%40awork3.anarazel.de - # Fix: Needs to be re-tested for GitHub Actions. - TEST_JOBS: 8 - - CCACHE_DIR: ${{ github.workspace }}/ccache_dir MACPORTS_CACHE: ${{ github.workspace }}/macports-cache MESON_FEATURES: >- @@ -497,44 +570,28 @@ jobs: -c debug_parallel_query=regress steps: - - *checkout_step + - *nix_sysinfo_step - - name: Sysinfo - run: | - id - uname -a - ulimit -a -H && ulimit -a -S - env + - *checkout_step - name: Setup core files run: | mkdir -p $HOME/cores sudo sysctl kern.corefile="$HOME/cores/core.%P" - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-macos-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-macos-${{ github.ref_name }}- - ccache-macos- - - - name: Compute MacPorts cache key + - name: "Macports: Compute cache key" id: mpkey run: | macos_major=$(sw_vers -productVersion | sed 's/\..*//') pkglist_hash=$(printf '%s' "$MACOS_PACKAGE_LIST" | md5 -q) script_hash=$(md5 -q src/tools/ci/ci_macports_packages.sh) - echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}-${GITHUB_RUN_ID}" >> "$GITHUB_OUTPUT" - echo "restore-key=macports-${macos_major}-${pkglist_hash}-${script_hash}-" >> "$GITHUB_OUTPUT" + echo "key=macports-${macos_major}-${pkglist_hash}-${script_hash}" >> "$GITHUB_OUTPUT" - - name: Restore MacPorts cache + - name: "MacPorts: Restore cache" uses: actions/cache@v5 with: path: ${{ env.MACPORTS_CACHE }} key: ${{ steps.mpkey.outputs.key }} - restore-keys: ${{ steps.mpkey.outputs.restore-key }} # Use MacPorts, even though Homebrew is installed. The installation # of the additional packages we need would take quite a while with @@ -546,7 +603,7 @@ jobs: # the large MacPort tree around to figure out that p5-io-tty is # actually p5.34-io-tty. Using the unversioned name works, but # updates MacPorts every time. - - name: Install dependencies (MacPorts) + - name: "MacPorts: Install dependencies" env: # Pass token so the script's GitHub API call to list MacPorts # releases isn't subject to the 60/h/IP unauthenticated rate @@ -560,11 +617,14 @@ jobs: echo /opt/local/sbin >> "$GITHUB_PATH" echo /opt/local/bin >> "$GITHUB_PATH" + - *ccache_restore_step + - name: Configure + env: + PKG_CONFIG_PATH: /opt/local/lib/pkgconfig/ run: | - export PKG_CONFIG_PATH="/opt/local/lib/pkgconfig/" meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ --buildtype=debug \ -Dextra_include_dirs=/opt/local/include \ -Dextra_lib_dirs=/opt/local/lib \ @@ -574,25 +634,21 @@ jobs: build - name: Build - run: ninja -C build -j${BUILD_JOBS} ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: | - ulimit -c unlimited # default is 0 - ulimit -n 1024 # default is 256, pretty low - meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + env: + # default is 256, pretty low + ADDITIONAL_SETUP: ulimit -n 1024 + run: *meson_test_world_cmd - name: Core backtraces - if: failure() + if: failure() && !cancelled() run: src/tools/ci/cores_backtrace.sh macos "$HOME/cores" - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: macos-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-vs: @@ -605,10 +661,10 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 8 # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' + TAR: "c:/windows/system32/tar.exe" MESON_FEATURES: >- -Dcpp_args=/std:c++20 @@ -618,13 +674,13 @@ jobs: -Dssl=openssl -Dplperl=enabled -Dplpython=enabled - TAR: "c:/windows/system32/tar.exe" defaults: run: shell: cmd steps: - - name: Disable Windows Defender + - &windows_disable_defender + name: Disable Windows Defender shell: powershell run: | Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable @@ -723,33 +779,36 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - name: Configure run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson setup --backend ninja %MESON_COMMON_PG_CONFIG_ARGS% %MESON_FEATURES% --buildtype debug -Db_pch=true -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include -DTAR=%TAR% build + meson setup ^ + --backend ninja ^ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} ^ + ${{env.MESON_FEATURES}} ^ + --buildtype debug ^ + -Db_pch=true ^ + -Dextra_lib_dirs=d:\openssl\1.1\lib -Dextra_include_dirs=d:\openssl\1.1\include ^ + -DTAR=${{env.TAR}} ^ + build - name: Build run: | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - ninja -C build %MBUILD_TARGET% + ninja -C build ${{env.MBUILD_TARGET}} ninja -C build -t missingdeps - name: Test world - run: | - call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 - meson test %MTEST_ARGS% --num-processes %TEST_JOBS% + env: + ADDITIONAL_SETUP: | + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-vs-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step windows-mingw: @@ -762,7 +821,7 @@ jobs: runs-on: windows-2022 timeout-minutes: 60 env: - TEST_JOBS: 4 # higher concurrency causes occasional failures + # Avoid port conflicts between concurrent tap tests PG_TEST_USE_UNIX_SOCKETS: 1 PG_REGRESS_SOCK_DIR: 'd:\pgsock' TAR: "c:/windows/system32/tar.exe" @@ -776,7 +835,6 @@ jobs: MESON_FEATURES: >- -Dnls=disabled - CCACHE_DIR: D:/a/ccache CCACHE_MAXSIZE: "500M" CCACHE_SLOPPINESS: pch_defines,time_macros CCACHE_DEPEND: 1 @@ -786,17 +844,7 @@ jobs: shell: 'D:\msys64\usr\bin\bash.exe --login -eo pipefail "{0}"' steps: - - name: Disable Windows Defender - shell: powershell - run: | - Set-MpPreference -DisableRealtimeMonitoring $true -SubmitSamplesConsent NeverSend -MAPSReporting Disable - # Verify Defender status - $status = Get-MpComputerStatus -ErrorAction SilentlyContinue - if ($status) { - Write-Host "RealTimeProtectionEnabled: $($status.RealTimeProtectionEnabled)" - Write-Host "AntivirusEnabled: $($status.AntivirusEnabled)" - } - + - *windows_disable_defender - *checkout_step # Relocate the preinstalled MSYS2 tree from C:\ (slow system disk) to @@ -835,6 +883,8 @@ jobs: ${MINGW_PACKAGE_PREFIX}-readline \ ${MINGW_PACKAGE_PREFIX}-zlib + - *nix_sysinfo_step + - name: Install additional dependencies run: | # Pin IPC::Run to NJM/IPC-Run-20250809.0; TODDR/IPC-Run-20260322.0 @@ -845,42 +895,32 @@ jobs: - name: Setup socket directory shell: cmd - run: mkdir %PG_REGRESS_SOCK_DIR% + run: mkdir ${{env.PG_REGRESS_SOCK_DIR}} - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-mingw-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-mingw-${{ github.ref_name }}- - ccache-mingw- + - *ccache_restore_step - name: Configure run: | meson setup \ - ${MESON_COMMON_PG_CONFIG_ARGS} \ + ${{env.MESON_COMMON_PG_CONFIG_ARGS}} \ -Ddebug=true -Doptimization=g -Db_pch=true \ - ${MESON_COMMON_FEATURES} \ - ${MESON_FEATURES} \ - -DTAR=${TAR} \ + ${{env.MESON_COMMON_FEATURES}} \ + ${{env.MESON_FEATURES}} \ + -DTAR=${{env.TAR}} \ build - name: Build - run: ninja -C build ${MBUILD_TARGET} + run: *ninja_build_command + + - *ccache_save_step - name: Test world - run: meson test ${MTEST_ARGS} --num-processes ${TEST_JOBS} + run: *meson_test_world_cmd # FIX: We need to collect crashlogs but they are not collected. cdb.exe # is installed on the runner so it needs to be configured. - - name: Upload logs - if: failure() - uses: actions/upload-artifact@v7 - with: - name: windows-mingw-logs-${{ github.run_id }} - path: *log_paths - if-no-files-found: ignore + - *upload_logs_step + # Test that code can be built with both gcc and clang without warnings, # with various combinations of cassert/dtrace flags. Trace probes have @@ -900,24 +940,12 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 container: - image: ${{ needs.setup.outputs.linux_ci_image }} + image: ${{ needs.setup.outputs.container_linux_ci_docs }} env: - BUILD_JOBS: 4 - CCACHE_DIR: /tmp/ccache_dir # Use larger ccache cache as this job compiles with multiple # compilers / flag combinations. CCACHE_MAXSIZE: "1G" steps: - - *checkout_step - - - name: Restore ccache - uses: actions/cache@v5 - with: - path: ${{ env.CCACHE_DIR }} - key: ccache-compiler-warnings-${{ github.ref_name }}-${{ github.run_id }} - restore-keys: | - ccache-compiler-warnings-${{ github.ref_name }}- - ccache-compiler-warnings- - name: Sysinfo run: | @@ -929,83 +957,108 @@ jobs: clang -v env + - *checkout_step + + - *ccache_restore_step + - name: Setup workspace run: | echo "COPT=-Werror" > src/Makefile.custom - mkdir -p "$CCACHE_DIR" # gcc, cassert off, dtrace on - name: gcc warnings + (dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # gcc, cassert on, dtrace off - name: gcc warnings + (cassert) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ --enable-cassert \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin # clang, cassert off, dtrace off - name: clang warnings - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + # clang, cassert on, dtrace on - name: clang warnings + (cassert + dtrace) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache clang.cache \ --enable-cassert \ --enable-dtrace \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ CC="ccache clang" CXX="ccache clang++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + - name: mingw warnings (cross compilation) - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --host=x86_64-w64-mingw32ucrt \ --enable-cassert \ --without-icu \ CC="ccache x86_64-w64-mingw32ucrt-gcc" \ CXX="ccache x86_64-w64-mingw32ucrt-g++" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} world-bin + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} world-bin + ### # Verify docs can be built ### # XXX: Only do this if there have been changes in doc/ since last build - name: Build documentation - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ --cache gcc.cache \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -C doc + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -C doc ### # Verify headerscheck / cpluspluscheck succeed @@ -1015,12 +1068,19 @@ jobs: # - Use -fmax-errors, as particularly cpluspluscheck can be very verbose ### - name: headerscheck + cpluspluscheck - if: always() + if: ${{ !cancelled() }} run: | + echo "::group::configure" ./configure \ - ${LINUX_CONFIGURE_FEATURES} \ + ${{env.LINUX_CONFIGURE_FEATURES}} \ --cache gcc.cache \ --quiet \ CC="ccache gcc" CXX="ccache g++" CLANG="ccache clang" - make -s -j${BUILD_JOBS} clean - make -s -j${BUILD_JOBS} -k ${CHECKFLAGS} headerscheck cpluspluscheck EXTRAFLAGS='-fmax-errors=10' + echo "::endgroup::" + + make -s -j${{env.BUILD_JOBS}} clean + make -s -j${{env.BUILD_JOBS}} -k ${{env.CHECKFLAGS}} \ + headerscheck cpluspluscheck \ + EXTRAFLAGS='-fmax-errors=10' + + - *ccache_save_step -- 2.54.0.380.gc69baaf57b --rv3g7aw7ud36z5b5 Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6a-0003-disable-cirrus.patch" ^ permalink raw reply [nested|flat] 249+ messages in thread
end of thread, other threads:[~2026-06-01 19:09 UTC | newest] Thread overview: 249+ messages (download: mbox mbox.gz follow: Atom feed) -- links below jump to the message on this page -- 2026-04-27 14:01 [PATCH v20 1/3] Avoid orphaned objects dependencies Bertrand Drouvot <bertranddrouvot.pg@gmail.com> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de> 2026-06-01 19:09 [PATCH v6a 2/5] gha: Andres' revisions Andres Freund <andres@anarazel.de>
This inbox is served by agora; see mirroring instructions for how to clone and mirror all data and code used for this inbox